#include <QStringView>  // 确保包含此头文件
#include "xmlparser.h"
#include <QFile>
#include <QXmlStreamWriter>
#include <QDomDocument>
#include <QDebug>
#include <QStringConverter> // Qt 6 需包含该头文件（若未包含）

using namespace TestDataModel;  // 简化命名空间引用

QList<ConfigItem> XmlParser::parseConfigFile(const QString& filePath) {
    QList<ConfigItem> configItems;
    QFile file(filePath);

    // 1. 打开配置文件
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
        qWarning() << "配置文件打开失败：" << filePath;
        return configItems;
    }

    // 2. 解析XML文档
    QDomDocument doc;
    QString errorMsg;
    int errorLine = 0;
    if (!doc.setContent(&file, &errorMsg, &errorLine)) {
        qWarning() << "XML解析失败（行" << errorLine << "）：" << errorMsg;
        file.close();
        return configItems;
    }
    file.close();

    // 3. 提取根节点（假设配置文件根节点为 <ConfigData>）
    QDomElement root = doc.documentElement();
    if (root.tagName() != "ConfigData") {
        qWarning() << "配置文件根节点错误，应为 <ConfigData>";
        return configItems;
    }

    // 4. 遍历所有 <ConfigItem> 节点，解析为 ConfigItem 对象
    QDomNodeList itemNodes = root.elementsByTagName("ConfigItem");
    for (int i = 0; i < itemNodes.size(); i++) {
        QDomElement itemElem = itemNodes.at(i).toElement();
        ConfigItem configItem = ConfigItem::fromDomElement(itemElem);  // 使用 datamodel 提供的反序列化方法
        configItems.append(configItem);
    }

    qInfo() << "配置文件解析成功，共加载" << configItems.size() << "个配置项";
    return configItems;
}

// 实现 loadTestCases：从XML文件读取测试案例列表
QList<TestCase> XmlParser::loadTestCases(const QString& filePath) {
    QList<TestCase> testCases;
    QFile file(filePath);

    // 打开XML文件
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
        qWarning() << "XML文件打开失败：" << file.errorString();
        return testCases;
    }

    QDomDocument doc;
    QString errorMsg;
    int errorLine = 0;
    // 解析XML
    if (!doc.setContent(&file, false, &errorMsg, &errorLine)) {
        qWarning() << "XML解析失败（行" << errorLine << "）：" << errorMsg;
        file.close();
        return testCases;
    }
    file.close();

    // 根节点：<TestCases>
    QDomElement root = doc.documentElement();
    if (root.tagName() != "TestCases") {
        qWarning() << "XML根节点错误（应为<TestCases>）";
        return testCases;
    }

    // 遍历所有测试案例节点：<TestCase>
    QDomNode caseNode = root.firstChild();
    while (!caseNode.isNull()) {
        QDomElement caseElem = caseNode.toElement();
        if (!caseElem.isNull() && caseElem.tagName() == "TestCase") {
            TestCase testCase;
            // 读取案例名称：<CaseName>xxx</CaseName>
            testCase.name = caseElem.firstChildElement("CaseName").text().trimmed();

            // 遍历所有测试组节点：<TestGroup>
            QDomNode groupNode = caseElem.firstChildElement("TestGroups").firstChild();
            while (!groupNode.isNull()) {
                QDomElement groupElem = groupNode.toElement();
                if (!groupElem.isNull() && groupElem.tagName() == "TestGroup") {
                    TestGroup testGroup;
                    // 读取组名称：<GroupName>组1</GroupName>
                    testGroup.groupName = groupElem.firstChildElement("GroupName").text().trimmed();

                    // 读取输入数据列表：<InputData>
                    QDomNode inputNode = groupElem.firstChildElement("InputData").firstChild();
                    while (!inputNode.isNull()) {
                        QDomElement inputElem = inputNode.toElement();
                        if (!inputElem.isNull() && inputElem.tagName() == "DataItem") {
                            TestDataItem item;
                            item.name = inputElem.attribute("name").trimmed();
                            item.type = inputElem.attribute("type").trimmed();
                            item.portOrCommid = inputElem.attribute("portOrCommid").toInt();
                            item.byteOffset = inputElem.attribute("byteOffset").toInt();
                            item.bitOffset = inputElem.attribute("bitOffset").toInt();
                            item.value = inputElem.text().trimmed();
                            testGroup.inputData.append(item);
                        }
                        inputNode = inputNode.nextSibling();
                    }

                    // 读取预期数据列表：<ExpectedData>
                    QDomNode expectedNode = groupElem.firstChildElement("ExpectedData").firstChild();
                    while (!expectedNode.isNull()) {
                        QDomElement expectedElem = expectedNode.toElement();
                        if (!expectedElem.isNull() && expectedElem.tagName() == "DataItem") {
                            TestDataItem item;
                            item.name = expectedElem.attribute("name").trimmed();
                            item.type = expectedElem.attribute("type").trimmed();
                            item.portOrCommid = expectedElem.attribute("portOrCommid").toInt();
                            item.byteOffset = expectedElem.attribute("byteOffset").toInt();
                            item.bitOffset = expectedElem.attribute("bitOffset").toInt();
                            item.value = expectedElem.text().trimmed();
                            testGroup.expectedData.append(item);
                        }
                        expectedNode = expectedNode.nextSibling();
                    }

                    testCase.testGroups.append(testGroup);
                }
                groupNode = groupNode.nextSibling();
            }

            if (!testCase.name.isEmpty()) {
                testCases.append(testCase);
            }
        }
        caseNode = caseNode.nextSibling();
    }

    qInfo() << "成功加载" << testCases.size() << "个测试案例";
    return testCases;
}

// 配套实现 saveTestCases：将测试案例列表写入XML（可选，用于保存编辑后的案例）
bool XmlParser::saveTestCases(const QString& filePath, const QList<TestCase>& testCases) {
    QFile file(filePath);
    if (!file.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) {
        qWarning() << "XML文件写入失败：" << file.errorString();
        return false;
    }

    QDomDocument doc;
    QDomProcessingInstruction xmlHeader = doc.createProcessingInstruction("xml", "version=\"1.0\" encoding=\"UTF-8\"");
    doc.appendChild(xmlHeader);

    // 根节点：<TestCases>
    QDomElement root = doc.createElement("TestCases");
    doc.appendChild(root);

    // 遍历所有测试案例
    for (const auto& testCase : testCases) {
        QDomElement caseElem = doc.createElement("TestCase");

        // 案例名称
        QDomElement caseNameElem = doc.createElement("CaseName");
        caseNameElem.appendChild(doc.createTextNode(testCase.name));
        caseElem.appendChild(caseNameElem);

        // 测试组列表节点：<TestGroups>
        QDomElement groupsElem = doc.createElement("TestGroups");
        for (const auto& testGroup : testCase.testGroups) {
            QDomElement groupElem = doc.createElement("TestGroup");

            // 组名称
            QDomElement groupNameElem = doc.createElement("GroupName");
            groupNameElem.appendChild(doc.createTextNode(testGroup.groupName));
            groupElem.appendChild(groupNameElem);

            // 输入数据列表：<InputData>
            QDomElement inputDataElem = doc.createElement("InputData");
            for (const auto& inputItem : testGroup.inputData) {
                QDomElement itemElem = doc.createElement("DataItem");
                itemElem.setAttribute("name", inputItem.name);
                itemElem.setAttribute("type", inputItem.type);
                itemElem.setAttribute("portOrCommid", inputItem.portOrCommid);
                itemElem.setAttribute("byteOffset", inputItem.byteOffset);
                itemElem.setAttribute("bitOffset", inputItem.bitOffset);
                itemElem.appendChild(doc.createTextNode(inputItem.value));
                inputDataElem.appendChild(itemElem);
            }
            groupElem.appendChild(inputDataElem);

            // 预期数据列表：<ExpectedData>
            QDomElement expectedDataElem = doc.createElement("ExpectedData");
            for (const auto& expectedItem : testGroup.expectedData) {
                QDomElement itemElem = doc.createElement("DataItem");
                itemElem.setAttribute("name", expectedItem.name);
                itemElem.setAttribute("type", expectedItem.type);
                itemElem.setAttribute("portOrCommid", expectedItem.portOrCommid);
                itemElem.setAttribute("byteOffset", expectedItem.byteOffset);
                itemElem.setAttribute("bitOffset", expectedItem.bitOffset);
                itemElem.appendChild(doc.createTextNode(expectedItem.value));
                expectedDataElem.appendChild(itemElem);
            }
            groupElem.appendChild(expectedDataElem);

            groupsElem.appendChild(groupElem);
        }
        caseElem.appendChild(groupsElem);
        root.appendChild(caseElem);
    }

    // 写入文件（格式化XML，便于阅读）
    QTextStream out(&file);
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
    out.setEncoding(QStringConverter::Utf8);
#else
    out.setCodec("UTF-8");
#endif
    doc.save(out, 4); // 缩进4个空格
    file.close();

    qInfo() << "成功保存" << testCases.size() << "个测试案例到" << filePath;
    return true;
}
